package org.example.http;

import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public class HttpServletRequestImpl implements HttpServletRequest {

    private Socket socket;
    private InputStream inputStream;
    private String method;
    private String uri;
    private String protocol;
    private Map<String,String> headers = new LinkedHashMap<>();
    // 参数集合
    private Map<String,List<String>> parameters = new LinkedHashMap<>();
    private String queryString;
    public HttpServletRequestImpl(Socket socket) {
        this.socket = socket;
        try {
            this.inputStream = socket.getInputStream();
            byte[] bytes = new byte[1024];
            int length = 0;
            length = inputStream.read(bytes);
            String requestContent = new String(bytes, 0, length);
//            System.out.println(requestContent);
            String[] lines = requestContent.split("\r\n");
            String[] items = lines[0].split(" ");
            method = items[0];
            uri = items[1];
            protocol = items[2];
            for (int i = 1; i < lines.length; i++) {
                if (lines[i].isEmpty()) {
                    // 请求头解析完成
                    break;
                }
                String[] headerItems = lines[i].split(": ");
                // 忽略请求头的大小写
                headers.put(headerItems[0].toLowerCase(), headerItems[1]);
            }
            // 打印请求头
            System.out.println("---------------------打印请求头----------------------");
            System.out.println(lines[0]);
            headers.forEach((k,v)->{
                System.out.println(k+": "+v);
            });

            // 解析请求参数
            if(uri.contains("?")){
                queryString = uri.split("\\?")[1];
                // 解码URL
                queryString = URLDecoder.decode(queryString, "UTF-8");
                parseRequestParameter(queryString);
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private void parseRequestParameter(String queryString){
        // queryString => a=1&b=2&a=3&c=&d
        if(queryString == null || queryString.isBlank()){
            return;
        }
        String[] items = queryString.split("&");
        for (String item : items) {
            String[] splits = item.split("=");
            String name = splits[0];
            String value = splits.length == 2 ? splits[1] : null;
            List<String> values = parameters.get(name);
            if(values == null){
                values = new ArrayList<>();
                parameters.put(name,values);
            }
            values.add(value);
        }
    }

    @Override
    public InputStream getInputStream() {
        return inputStream;
    }

    @Override
    public String getMethod() {
        return method;
    }

    @Override
    public String getRequestURI() {
        return uri;
    }

    @Override
    public String getProtocol() {
        return protocol;
    }

    @Override
    public String getHeader(String name) {
        return "";
    }

    @Override
    public Cookie[] getCookies() {
        String cookieStr = headers.get("cookie");
        if(cookieStr == null) return null;
        String[] cookies = cookieStr.split(";\\s*");
        List<Cookie> cookieList = new ArrayList<>();
        for (String cookie : cookies) {
            String[] items = cookie.split("=");
            String name = items[0];
            String value = items[1];
            Cookie c = new CookieImpl(name,value);
            cookieList.add(c);
        }
        return cookieList.toArray(new Cookie[0]);
    }

    HttpSession session = null;
    @Override
    public HttpSession getSession() {
        // 会话对象不为空, 则直接返回会话对象
        if(session != null){
            return session;
        }
        // 从cookie中提取会话id
        Cookie[] cookies = getCookies();
        String sessionId = null;
        if(cookies != null) {
            for (Cookie cookie : cookies) {
                if(cookie.getName().equals("JSESSIONID")){
                    sessionId = cookie.getValue();
                    break;
                }
            }
        }
        // 如果会话ID不为空, 则表示已经为浏览器创建了会话对象
        if (sessionId != null) {
            // 尝试从会话容器获取会话
            // 问题: 会话id 不为空, 但是会话容器中找不到指定的会话对象?
            // 原因: 会话自动失效, 超过失效时间30分钟
            session = HttpSessionImpl.sessions.get(sessionId);
            if(session != null) {
                // 实现会话自动失效:
                // 方法1. 启动一个线程, 开启定时任务, 定期删除过期会话
                // 方法2. 返回会话之前, 判断会话是否失效
                // 方法2
                // 计算距离上一次访问会话的时间
                long times = System.currentTimeMillis() - ((HttpSessionImpl) session).lastAccessedTime;
                long minutes = times / 1000 / 60;
                if(minutes < session.getCreationTime()){
                    // 会话对象未失效, 更新最后的访问时间
                    ((HttpSessionImpl) session).lastAccessedTime =  System.currentTimeMillis();
                } else {
                    // 会话对象失效, 从会话容器中删除会话对象
                    HttpSessionImpl.sessions.remove(sessionId);
                    session = null;
                }
            }
        }
        // 再次判断会话是否为空
        if (session == null) {
            // 会话对象为空, 则创建新的会话对象
            session = new HttpSessionImpl();
        }
        // 会话对象一定不为空
        return session;
    }

    @Override
    public String getParameter(String name) {
        List<String> values = parameters.get(name);
        String value = values != null && values.size() > 0 ? values.get(0) : null;
        return value;
    }

    @Override
    public String[] getParameterValues(String name) {
        List<String> values = parameters.get(name);
        return  values != null ? values.toArray(new String[0]) : null;
    }

    @Override
    public String getQueryString() {
        return queryString;
    }

    @Override
    public void setCharacterEncoding(String env) throws UnsupportedEncodingException {

    }
}
